package tech.springboot.springtasks.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;

/**
 * 启用异步支持：
 * @EnableAsync注解告诉Spring Boot启动类或配置类启用异步方法的支持
 * 创建异步方法：
 * asyncMethodWithVoidReturnType：这是一个简单的异步方法，没有返回值。
 * asyncMethodWithReturnType：这个方法返回一个CompletableFuture<String>，允许你在方法完成后获取结果。
 * 调用异步方法：
 * 在CommandLineRunner接口的run方法中，我们调用了两个异步方法。
 * 第一个方法没有返回值，因此直接调用即可。
 * 第二个方法返回一个CompletableFuture，我们可以使用thenAccept方法在异步操作完成后处理结果。
 *
 * 注意事项
 * 线程池配置：
 * 默认情况下，Spring使用SimpleAsyncTaskExecutor来执行异步方法，但这并不是一个真正的线程池。
 * 对于生产环境，建议配置自定义的线程池。可以通过实现AsyncConfigurer接口来配置线程池。
 */
@EnableAsync
@Configuration
public class AsyncTaskConfig implements AsyncConfigurer {

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(7);
        executor.setMaxPoolSize(42);
        executor.setQueueCapacity(11);
        executor.setThreadNamePrefix("local1-executor-");
        executor.initialize();
        return executor;
    }

    @Override
    public Executor getAsyncExecutor() {
        return taskExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }
}

class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        System.err.println("Method '" + method.getName() + "' threw exception : "
                + ex.getMessage());
    }
}